package com.katesoft.scale4j.rttp.hibernate;

import com.hazelcast.hibernate.HazelcastTimestamper;
import com.hazelcast.hibernate.collection.HazelcastCollectionRegion;
import com.hazelcast.hibernate.entity.HazelcastEntityRegion;
import com.hazelcast.hibernate.query.HazelcastQueryResultsRegion;
import com.hazelcast.hibernate.timestamp.HazelcastTimestampsRegion;
import com.katesoft.scale4j.log.Logger;
import com.katesoft.scale4j.log.LogFactory;
import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.CollectionRegion;
import org.hibernate.cache.EntityRegion;
import org.hibernate.cache.QueryResultsRegion;
import org.hibernate.cache.RegionFactory;
import org.hibernate.cache.TimestampsRegion;
import org.hibernate.cache.access.AccessType;
import org.hibernate.cfg.Settings;
import org.springframework.beans.factory.annotation.Required;

import java.util.Properties;

/**
 * This class provides hibernate second level cache solution.
 *
 * @author kate2007
 */
public class RttpHibernateCacheRegionFactory implements RegionFactory
{
    private final Logger logger = LogFactory.getLogger(RttpHibernateCacheRegionFactory.class);
    private SpringHazelcastBridge springHazelcastBridge;

    public RttpHibernateCacheRegionFactory()
    {
        super();
    }

    @SuppressWarnings({"UnusedDeclaration"})
    public RttpHibernateCacheRegionFactory(final Properties properties)
    {
        this();
    }

    @Override
    public AccessType getDefaultAccessType()
    {
        return AccessType.READ_WRITE;
    }

    @Override
    public long nextTimestamp()
    {
        return HazelcastTimestamper.nextTimestamp(springHazelcastBridge.getHazelcastInstance());
    }

    @Override
    public void start(Settings settings,
                      Properties properties) throws CacheException
    {
        logger.info("Starting up HazelcastCacheRegionFactory...");
        springHazelcastBridge.getHazelcastLauncher().loadInstance(properties);
    }

    @Override
    public void stop()
    {
        logger.info("Shutting down RttpHibernateCacheRegionFactory...");
        springHazelcastBridge.getHazelcastLauncher().stop();
    }

    @Override
    public boolean isMinimalPutsEnabledByDefault()
    {
        return false;
    }

    @Override
    public CollectionRegion buildCollectionRegion(String regionName,
                                                  Properties properties,
                                                  CacheDataDescription metadata) throws CacheException
    {
        return new HazelcastCollectionRegion(springHazelcastBridge.getHazelcastInstance(), regionName, metadata);
    }

    @SuppressWarnings({"unchecked"})
    @Override
    public EntityRegion buildEntityRegion(String regionName,
                                          Properties properties,
                                          CacheDataDescription metadata) throws CacheException
    {
        return new HazelcastEntityRegion(springHazelcastBridge.getHazelcastInstance(), regionName, metadata);
    }

    @Override
    public QueryResultsRegion buildQueryResultsRegion(String regionName,
                                                      Properties properties) throws CacheException
    {
        return new HazelcastQueryResultsRegion(springHazelcastBridge.getHazelcastInstance(), regionName);
    }

    @Override
    public TimestampsRegion buildTimestampsRegion(String regionName,
                                                  Properties properties) throws CacheException
    {
        return new HazelcastTimestampsRegion(springHazelcastBridge.getHazelcastInstance(), regionName);
    }

    @Required
    public void setSpringHazelcastBridge(SpringHazelcastBridge springHazelcastBridge)
    {
        this.springHazelcastBridge = springHazelcastBridge;
        logger.info("spring hazelcast bridge [%s] registered", springHazelcastBridge);
    }
}
